const fs = require('fs');
const path = require('path');

/**
 * 读取文件夹下的所有文件，并补全路径
 * @param {string} dir 文件夹路径
 * @returns {string[]}
 */
async function readdir(dir) {
  const list = await fs.promises.readdir(dir);
  return list.map((item) => {
    return path.join(dir, item);
  });
}

exports.readdir = readdir;

/**
 * 判断是否为文件夹
 * @param {string} filePath 文件路径
 * @returns {boolean}
 */
async function isDirectory(filePath) {
  return (await fs.promises.stat(filePath)).isDirectory();
}

exports.isDirectory = isDirectory;

/**
 * 遍历文件夹
 * @param {string} dir 文件夹路径
 * @returns {Promise<string[]>}
 */
async function traversaDir(dir) {
  const stack = [dir];
  const list = [];
  while (stack.length > 0) {
    const dir = stack.pop();
    const fileList = await readdir(dir);
    for (const item of fileList) {
      (await isDirectory(item) ? stack : list).push(item);
    }
  }
  return list;
}

exports.traversaDir = traversaDir;

/**
 * 洋葱模型
 * @param {function[]} list 
 * @param {function} callback 
 */
function onion(list, callback) {
  const funcList = [...list, callback];
  const layerList = [];
  for (let i = 0; i < funcList.length; i++) {
    layerList.push(async (ctx) => {
      try {
        await funcList[i](ctx, async (err) => {
          if (err) {
            return callback(err);
          }
          await layerList[i + 1](ctx);
        });
      } catch (error) {
        callback(error);
      }
    });
  }
  return layerList[0];
}

exports.onion = onion;

/**
 * 休眠
 * @param {number} interval 休眠时间
 */
function sleep(interval) {
  return new Promise(resolve => setTimeout(resolve, interval));
}

exports.sleep = sleep;